#coding=utf-8
#!/usr/bin/python

'''
Created on 2012-11-17

@author: Neo.Chen
'''

'''
功能：自动应答的小黄鸡
'''


import os
import sys
import time
import string
import logging
import threading
import socket
import select
import http.client
import simsimi

from ktlib import ktlib
from ktlib import kttlv

g_server_ip = "172.16.3.158"
#g_server_ip = "172.21.1.69"
g_server_port = 4504
g_recv_timeout = 60     #60秒超时
g_sky_id = 405352989
#DEBUG_SESSION = "{1EB2B1E2-F615-4d91-A2B3-5924443DB82E}"
DEBUG_SESSION = "5C71F08BABA3FEDED89B71E2B64F83D6-n2"
g_buffer = b""
g_user_name = "boss"


def sendtlv(sock, cmd, data):
    head = kttlv.make_head(cmd, len(data)+12)
    tlv = head + data
    sock.send(tlv)

CMDNO_CLIENT_QUICK_LOGIN_REQ = 0x1105
x1105_tag_session = 1
x1105_tag_usrid = 2
x1105_tag_roomid = 8
x1105_tag_channelid = 10
x1105_tag_json = 16
CH_CMD= 0 + 1
CH_CHAT= 0 + 2

CMDNO_MSG_SEND_REQ = 0x1110
x1110_tag_session = 1
x1110_tag_src_usrid = 2
x1110_tag_dst_usrid = 3
x1110_tag_channelid = 4
x1110_tag_roomid = 5
x1110_tag_msgtype = 6
x1110_tag_operater_l = 8
x1110_tag_operater_h = 9
x1110_tag_issetopera = 10
x1110_tag_msginfo = 11
#内容
chat_tag_content = 1
#类型
Mit_Chat= 1
#
Mat_UnLimit_chat= 0x0020

CMDNO_MSG_SEND_NOTIFY = 0x3110
x3110_tag_src_usrid = 1
x3110_tag_dst_usrid = 2
x3110_tag_msgtype = 7
x3110_tag_msginfo = 12


def send_login(ts, room_id, sky_id):
    #发送登录请求
    data = kttlv.encoder_string(x1105_tag_session, DEBUG_SESSION) + \
        kttlv.encoder_int32(x1105_tag_usrid, sky_id) + \
        kttlv.encoder_int32(x1105_tag_roomid, room_id) + \
        kttlv.encoder_int32(x1105_tag_channelid, CH_CMD) + \
        kttlv.encoder_int32(x1105_tag_channelid, CH_CHAT) + \
        kttlv.encoder_string(x1105_tag_json, g_user_name)   #服务特殊处理，用json字段保存昵称
    sendtlv(ts, CMDNO_CLIENT_QUICK_LOGIN_REQ, data)


def send_heart_beat(ts, room_id, sky_id):
    #发送心跳包请求
    CMDNO_KEEP_LIVE_REQ = 0x1000
    data = b""
    sendtlv(ts, CMDNO_KEEP_LIVE_REQ, data)

def send_chat(ts, room_id, sky_id, dst_id, message):
    #发送发言请求
    message_utf8 = message.encode('utf8')
    content = kttlv.encoder_bytes(chat_tag_content, message_utf8)

    data = kttlv.encoder_string(x1110_tag_session, DEBUG_SESSION) + \
        kttlv.encoder_int32(x1110_tag_src_usrid, sky_id) + \
        kttlv.encoder_int32(x1110_tag_dst_usrid, dst_id) + \
        kttlv.encoder_int16(x1110_tag_roomid, room_id) + \
        kttlv.encoder_int32(x1110_tag_channelid, CH_CHAT) + \
        kttlv.encoder_int16(x1110_tag_msgtype, Mit_Chat) + \
        kttlv.encoder_int32(x1110_tag_operater_l, Mat_UnLimit_chat) + \
        kttlv.encoder_int32(x1110_tag_operater_h, 0) + \
        kttlv.encoder_int8(x1110_tag_issetopera, 1) + \
        kttlv.encoder_bytes(x1110_tag_msginfo, content)
    sendtlv(ts, CMDNO_MSG_SEND_REQ, data)

def on_idle(ts, room_id, sky_id):
    send_heart_beat(ts, room_id, sky_id)

#自动应答
def on_auto_chat(ts, room_id, sky_id, srcid, content):
    sim = simsimi.SimSimi()
    msg = sim.chat(content)
    send_chat(ts, room_id, sky_id, srcid, msg)


def on_recv(ts, room_id, sky_id, buffer):
    global g_buffer     #修改全局变量
    g_buffer = g_buffer + buffer
    while True:
        data_len = len(g_buffer)
        #包头是否完整
        if data_len < 12:
            break
        #数据包是否完整
        (cmd_id, length) = kttlv.parse_head(g_buffer)
        if data_len < length:
            break
        #解析协议
        if cmd_id == CMDNO_MSG_SEND_NOTIFY:
            tlvbuf = g_buffer[12:data_len-12]
            msgtype = kttlv.to_int(tlvbuf, x3110_tag_msgtype)
            if msgtype == Mit_Chat:
                srcid = kttlv.to_int(tlvbuf, x3110_tag_src_usrid)
                dstid = kttlv.to_int(tlvbuf, x3110_tag_dst_usrid)
                msginfo = kttlv.to_bytes(tlvbuf, x3110_tag_msginfo)
                content = kttlv.to_string(msginfo, chat_tag_content)
                print(content)
                if dstid == sky_id:
                    on_auto_chat(ts, room_id, sky_id, srcid, content)
        #完成一个包的处理，删内存
        g_buffer = g_buffer[length:]



def chat_room(room_id):
    logging.info("chat_room, entry, room:%d" % (room_id))
    conn = 0
    ts = socket.socket()
    try:
        ts.connect((g_server_ip, g_server_port))
        conn = 1
    except:
        ts.close()
        logging.warning("chat_room, connect failed!")
    if conn != 1:
        return False

    #发送登录请求
    send_login(ts, room_id, g_sky_id)

    #接收数据
    #并且每隔60秒发送一个心跳包
    tmLast = time.time()
    while True:
        tmNow = time.time()
        if tmNow - tmLast > 60:
            tmLast = tmNow
            on_idle(ts, room_id, g_sky_id)
        #接收数据
        rl,wl,xl = select.select([ts.fileno()],[],[ts.fileno()], 10)
        if len(xl) > 0:
            ts.close()
            print("socket closed.")
            break
        if len(rl) > 0:
            #try:
                buffer = ts.recv(10000)
                data_len = len(buffer)
                if data_len == 0:
                    raise
                on_recv(ts, room_id, g_sky_id, buffer)
            #except:
            #    ts.close()
            #    print("socket closed.")
    logging.info("chat_room, exit")

def xiaohuangji():
    chat_room(30011)

def main():
    print("main start...")
    logging.basicConfig(level=logging.DEBUG,
                format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                datefmt='%a, %d %b %Y %H:%M:%S',
                filename='xiaohuangji.log',
                filemode='w')
    xiaohuangji()

if __name__ == '__main__':
    ktlib.ForkMySelf("xiaohuangji", 3)
    if sys.platform != 'win32':
        try:
            main()
        except:
            ktlib.write_crash_log()
    else:
        main()
